<?php
/**
 * _obhandler is the base for all output handlers
 *
 * @package Smernel
*/
	class _obhandler{
	
		/**
		 * HTTP Status
		 * @var integer
		 */
		var $status = 200;
		
		/**
		 * HTTP Response as per status code
		 * @var string
		 */
		var $response = 'OK';
		
		/**
		 * HTTP headers
		 * @var array
		 */
		var $headers = array(
			'Content-type'=>'text/html; charset=utf-8'
		);
		
		/**
		* HTTP Cookies
		* @var array
		*/
		var $cookies = array();
		
		/**
		* Outbut Buffer
		* @var string
		*/
		protected $ob = '';
		
		// We don't show off any more
		function __construct(){
			//$this->headers["X-Powered-By"] = sn()->server_software();
			//$this->headers["Server"] = $_SERVER['SERVER_SOFTWARE'].' '.Domain()->SOFTWARE;
		}
		
		/**
		* sets HTTP status
		* @param integer status
		*/
		function set_status($s){
			$this->status = $s;	
		}
		
		/**
		* gets header from member array
		* @param string header name
		* @returns string
		*/
		function get_header($h){
			return isset($this->headers[$h]) ? $this->headers[$h] : false;	
		}
		
		/**
		* sets header in member array
		* @param string header name
		* @param string header value
		*/
		function set_header($type, $setting){
			$this->headers[$type] = $setting;	
		}
		
		/**
		* unsets header in member array
		* @param string header name
		*/
		function remove_header($type){
			unset($this->headers[$type]);	
		}
		
		/**
		* sets a cookie to be sent at header push time
		* @param string cookie name
		* @param string cookie value
		* @param integer expires
		* @param string path
		* @param string domain
		* @param bool secure
		*/
		function setcookie($n, $v='', $x=0, $p='/', $d=SERVER_NAME, $s=false){
			$this->cookies[$n] = array($v, $x, $p, $d, $s);
		}
		
		/**
		* sets headers to request no cacheing on the client
		*/
		function cache_control(){
			$this->headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate';
			$this->headers['Pragma'] = 'no-cache';
			$this->headers['Expires'] = 'Sat, 1 Jan 2000 00:00:00 GMT';
		}
		
		/**
		* Clears php nested buffers and appends to internal buffer
		*/
		function scrape_php_buffer($clear_last=false){
			while(ob_get_level() > 1) ob_end_flush();
			$this->ln(ob_get_clean());
			if($clear_last) ob_end_flush();
		}
		
		/**
		* Puts headers
		*/
		function put_headers(){
			if(headers_sent()) return;
           /*if(headers_sent($file, $line)){
           			if(defined('HEADERS_SENT_BY')) trigger_error("HEADERS_SENT_BY: ".HEADERS_SENT_BY, E_USER_NOTICE);
           			back_error("Obhandler is tripping out. Context is ".CONTEXT.", ajax is '".req('smajax')."', ob_get_level is ".ob_get_level().", handler:".get_class(smout()->get_handle()).", backtrace (2) is", E_USER_NOTICE, 2);
           			//trigger_error('included files are: '.implode("\n", get_included_files()), E_USER_NOTICE);
                    // kill the script, giving line where user flushed
                    trigger_error("Headers already sent (output started at $file on line $line)", E_USER_ERROR);
            }*/
			$this->scrape_php_buffer();
			if($this->status == 200) header('HTTP/1.0 200 OK');
			else{
				$HTS = new HTTPStatus($this->status);
				header($HTS->header);
				$this->response = $HTS->response;
				if($HTS->message) $this->headers["Warn"] = $HTS->message;
			}
			foreach($this->headers as $type=>$setting) header("$type: $setting");
			foreach($this->cookies as $n=>$a) setcookie($n, $a[0], $a[1], $a[2], $a[3], $a[4]);
			sn()->fire_event('headers');
			while(!headers_sent()){
				if(ob_get_level()) ob_end_flush();
				flush();
				if(!ob_get_level()) break;
			}
			//define("HEADERS_SENT_BY", back_error("context: ".CONTEXT.", ajax: '".req('smajax')."', handler:".get_class(smout()->get_handle()).", backtrace (2):", E_USER_NOTICE, 2, 1));
			//error_log(req('smajax').' smash ob:'.ob_get_level(), E_USER_NOTICE);
		}
	
		/**
		* Cleans buffer
		*/
		function clean(){
			while(ob_get_level() > 1) ob_end_clean();
			$this->ob = '';	
		}
		
		/**
		* Appends to buffer
		*/
		function ln($s){
			$this->ob .= $s;	
		}
		
		/**
		* Flushes buffer incrementally
		*/
		function flush($i=1024){
			$this->put_headers();
			while($s = substr($this->ob, 0, $i)){
				echo $s;
				flush();
				$this->ob = substr($this->ob, $i);
			}	
		}
		
		/**
		* Puts a line immediately
		*/
		function putln($s){
			echo $s;
			if(ob_get_level()) ob_flush();
			flush();	
		}
		
		/**
		* alias of putln
		*/
		function send($s){
			$this->putln($s);	
		}
		
		/**
		* alias of putln
		*/
		function write($s=''){
			$this->send($s);
		}
		
		/**
		* not sure what this is for
		*/
		function headers_sent(){
			return headers_sent();	
		}
		
		/**
		* reports an error in this context
		*/
		function report_error($e){
			echo $e;	
		}
	
	}


